#include <time.h>
#include "misc.h"
#include "part1_shared.h"
#include "DEHT.h"

#define MAX_SIZE 256
#define ASCII_RANGE 95 
#define DIGIT_RANGE 10
#define LETTER_RANGE 52	
#define MAX_PASSWORD_LENGTH (MAX_INTPUT_SIZE - 1)
#define ALPHANUM_RANGE 39


#define TABLE_SEED (0x1100220033004400)
#define VALIDATION_SEED (0x0123012301230123)
#define BYTES_PER_VALIDATION_KEY 8

/****************************************************************************/
/* type definition of TERM_SYMBOL ! a struct containing all required to specify one*/
/****************************************************************************/

typedef struct  {
	
	char symbol; /* the actual symbol character of the symbol */
	int n; /* the maximum sequence length attached to the symbol(in case of '*' , '%' or '^' */
	char *possible_values; /* an array of possible values this symbol can generate(contant throughout the flow */
	LONG_INDEX_PROJ number_of_possible_passwords;	/* the range of possible value */

} TERM_SYMBOL;

/****************************************************************************/
/* type definition of TERM ! a struct containing all required to specify one*/
/****************************************************************************/

typedef struct  {

	LONG_INDEX_PROJ number_of_possible_passwords; /* number of possible passwords this term cam generate */
	int number_of_symbols; /* number of symbols in the current term (as defined in the specs file) */
	TERM_SYMBOL *symbols; /* an array of symbols the term consists of */

} TERM;

/****************************************************************************/
/* type definition of RULE ! a struct containing all required to specify one*/
/****************************************************************************/
typedef struct  {
	int number_of_terms; /* number of terms the rule consists of */
	int lexicon_size;	/* number of words in the lexicon file attached to the rule */
	char **lexicon;	/* an array of strings containing the words from the lexicon file */
	TERM *terms; /* an array of terms the rule consists of */
	LONG_INDEX_PROJ number_of_possible_passwords; /* the number of possible passwords this rule can generate */
	
}RULE;

/* creates a rule as struct from the given command line rule
   return -1 if the rule is invalid */
int create_rule(RULE *rule, char *rule_as_string, char **lexicon, LONG_INDEX_PROJ lexicon_size);

/* given a certain k, generates the kth password from a rule(created with create_rule) and puts it in dest*/
int generate_kth_password(LONG_INDEX_PROJ k, char *dest, RULE rule);

/* load lexicon from file to an array of string , puts the number of words in length*/
char** load_lexicon(char *lexfile_path, LONG_INDEX_PROJ* length);

/* count the number of letters in a word (not including symbols) */
int word_length(char *string);

/* frees the allocated memory for the rule */
void free_rule(RULE *rule);

/* free the lexicon buffer */
void free_lexicon(char **lexicon, LONG_INDEX_PROJ length);

/* hash function of type hashKeyIntoTableFunctionPtr */
int cryptHashToTable(const unsigned char * x, int inputLength, int numOfEntries);
/* hash function of type hashKeyforEfficientComparisonFunctionPtr */
int cryptHashTo64bit(const unsigned char * x, int inputLength, unsigned char * result);